/**
 * ===============================================================================
 * Copyright (C) 2012 Vadim Lopatin
 * Project: TAO Library
 * Package: ua.at.tsvetkov.memory
 * File:    VMRuntimeHack.java
 * ===============================================================================
 */
package ua.at.tsvetkov.memory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import ua.at.tsvetkov.util.Log;

/**
 * Hack for allocate additional memory.
 * @author Vadim Lopatin (2012)
 */
public class VMRuntimeHack {

	public static final VMRuntimeHack run	= new VMRuntimeHack();

	private Object	runtime				= null;
	private Method	trackAllocation	= null;
	private Method	trackFree			= null;

	public VMRuntimeHack() {
		boolean success = false;
		try {
			Class<?> cl = Class.forName("dalvik.system.VMRuntime");
			Method getRt = cl.getMethod("getRuntime", new Class[0]);
			runtime = getRt.invoke(null, new Object[0]);
			trackAllocation = cl.getMethod("trackExternalAllocation", new Class[] { long.class });
			trackFree = cl.getMethod("trackExternalFree", new Class[] { long.class });
			success = true;
		} catch (ClassNotFoundException e) {
		} catch (SecurityException e) {
		} catch (NoSuchMethodException e) {
		} catch (IllegalArgumentException e) {
		} catch (IllegalAccessException e) {
		} catch (InvocationTargetException e) {
		}
		if (!success) {
			Log.w("VMRuntime hack does not work!");
			runtime = null;
			trackAllocation = null;
			trackFree = null;
		}
	}

	public boolean trackAlloc(long size) {
		if (runtime == null)
			return false;
		try {
			Object res = trackAllocation.invoke(runtime, Long.valueOf(size));
			return (res instanceof Boolean) ? (Boolean) res : true;
		} catch (IllegalArgumentException e) {
			return false;
		} catch (IllegalAccessException e) {
			return false;
		} catch (InvocationTargetException e) {
			return false;
		}
	}

	public boolean trackFree(long size) {
		if (runtime == null)
			return false;
		try {
			Object res = trackFree.invoke(runtime, Long.valueOf(size));
			return (res instanceof Boolean) ? (Boolean) res : true;
		} catch (IllegalArgumentException e) {
			return false;
		} catch (IllegalAccessException e) {
			return false;
		} catch (InvocationTargetException e) {
			return false;
		}
	}

}
